﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace THenu.TinyHourseLib.DesignPattern.Behavioral_Patterns.Chain_of_Resp_Pattern
{
    /// <summary>
    /// A way of passing a request between a chain of objects
    /// </summary>
    public class ChainOfRespPattern :IPatternDemonstrate
    {
        public void StructuralCode()
        {
            // Setup Chain of Responsibility
            Handler h1 = new ConcreteHandler1();
            Handler h2 = new ConcreteHandler2();
            Handler h3 = new ConcreteHandler3();
            h1.SetSuccessor(h2);
            h2.SetSuccessor(h3);

            // Generate and process request
            int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 };

            foreach (int request in requests)
            {
                h1.HandleRequest(request);
            }
        }

        public string PatternDescription()
        {
            string description = @"
Definition
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

Participants

    The classes and objects participating in this pattern are:

Handler   (Approver)
·defines an interface for handling the requests
·(optional) implements the successor link
ConcreteHandler   (Director, VicePresident, President)
·handles requests it is responsible for
·can access its successor
·if the ConcreteHandler can handle the request, it does so; otherwise it forwards the request to its successor
Client   (ChainApp)
·initiates the request to a ConcreteHandler object on the chain";

            return description;
        }

        public void RealWorldExample()
        {
            // Setup Chain of Responsibility
            Approver larry = new Director();
            Approver sam = new VicePresident();
            Approver tammy = new President();

            larry.SetSuccessor(sam);
            sam.SetSuccessor(tammy);

            // Generate and process purchase requests
            Purchase p = new Purchase(2034, 350.00, "Assets");
            larry.ProcessRequest(p);

            p = new Purchase(2035, 32590.10, "Project X");
            larry.ProcessRequest(p);

            p = new Purchase(2036, 122100.00, "Project Y");
            larry.ProcessRequest(p);
        }
    }
}
